﻿using System.Drawing;
using System.Drawing.Drawing2D;
using GraphDrawing2.Canvas;
using GraphDrawing2.Core;

namespace GraphDrawing2.V2.Graph.Model
{
    public class LinkView : ILinkView
    {
        const int ARROW_WIDTH = 4;
        const int ARROW_HEIGHT = 10;
        const int ARROW_INSET = 2;
        readonly GraphicsPath interior;
        readonly GraphicsPath arrowInterior;
        readonly LineAppearance appearance;

        public LinkView()
        {
            interior = new GraphicsPath();
            appearance = new LineAppearance();
            appearance.Color = Color.Navy;
            appearance.Width = 2;
            arrowInterior = new GraphicsPath(FillMode.Winding);

            arrowInterior.AddPolygon(new[] {new PointF(-ARROW_WIDTH, -ARROW_HEIGHT), new PointF(0, -ARROW_HEIGHT + ARROW_INSET), new PointF(ARROW_WIDTH, -ARROW_HEIGHT), new PointF(0, 0)});
        }

        public void Update(PointF startPoint, PointF endPoint)
        {
            interior.Reset();
            var x = startPoint.X + (endPoint.X - startPoint.X)/2f;
            interior.AddBezier(startPoint, new PointF(x, startPoint.Y), new PointF(x, endPoint.Y), endPoint);
        }

        public void Render(DrawingContext dc)
        {
            var g = dc.graphics;
            using (g.DrawLocal())
            {
                g.SmoothingMode = SmoothingMode.AntiAlias;
                using (var p = appearance.CreatePen())
                using (var cap = new CustomLineCap(arrowInterior, null))
                {
                    cap.BaseInset = ARROW_INSET;
                    p.LineJoin = LineJoin.Miter;
                    p.CustomEndCap = cap;
                    g.DrawPath(p, interior);
                }
            }
        }
    }
}